package cn.felord.common.utils;


import net.minidev.json.JSONArray;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * The type Spring security authentication util.
 */
public final class AuthenticationUtil {

    /**
     * The constant anonymous.
     */
    public static final Authentication anonymous = new AnonymousAuthenticationToken("-1", "anonymousUser",
            AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));


    /**
     * The constant ATS_CLAIM.
     */
    public static final String ATS_CLAIM = "ats";


    private AuthenticationUtil() {
    }

    /**
     * 获取当前用户，永远不可能为空
     *
     * @return the authentication
     */
    public static Authentication currentUser() {
        return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).orElse(anonymous);
    }

    /**
     * Authorities set.
     *
     * @return the set
     */
    public static Set<String> currentAuthorities() {
        Authentication authentication = currentUser();
        if (authentication instanceof AnonymousAuthenticationToken) {
            return Collections.emptySet();
        }
        JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
        JSONArray array = (JSONArray)jwtAuthenticationToken.getTokenAttributes().get(ATS_CLAIM);
       return array.stream()
               .map(o -> (String) o)
               .collect(Collectors.toSet());
    }


    /**
     * Current user roles collection.
     *
     * @return the collection
     */
    public static Collection<? extends GrantedAuthority> currentUserRoles() {
        Collection<? extends GrantedAuthority> authorities = currentUser().getAuthorities();
        return CollectionUtils.isEmpty(authorities) ? Collections.emptyList() : authorities;
    }

    /**
     * Current user name string.
     *
     * @return the string
     */
    public static String currentUserName() {
        return currentUser().getName();
    }
}
